﻿''
''Copyright Zac McKenzie 2012
''

Imports System.Net
Imports System.Net.Sockets
Imports st = System.Text

Public Class telnetIF
    Shared telnetDelay = 500
    ' These vars can be formwide or local (in procedure) depending on how you want to use them.
    Dim remoteIPAddress As IPAddress
    Dim ep As IPEndPoint
    Dim tnSocket As Socket

    Public Shared commandList As List(Of String) = New List(Of String)

    Public Sub putCommandx(ByVal cmd As String)
        wizScheduleCheckerMain.updateStatus("Adding command for beyonWiz to execute ", commandList.Count)
        commandList.Add(cmd)
    End Sub

    Public Function executeCommand(ByVal ipaddr As String) As String
        establishConnection(ipaddr, "23")

        Dim RecvString As String = sendCommand()
        commandList.Clear()

        Return RecvString

    End Function
    Public Function doCommand(ByVal ipaddr As String, ByVal cmd As String, Optional ByVal keepConnection As Boolean = False) As String
        commandList.Clear()
        commandList.Add(cmd)
        If Not keepConnection Then endconnection()
        Return executeCommand(ipaddr)
    End Function

    Private Sub establishConnection(ByVal PIPAddress As String, ByVal PPort As String)
        'if kept connection open then job is done
        If tnSocket IsNot Nothing Then Exit Sub
        wizScheduleCheckerMain.updateStatus("Establishing connection to BeyonWiz box: ", PIPAddress)

        ' Get the IP Address and the Port and create an IPEndpoint (ep)
        remoteIPAddress = IPAddress.Parse(PIPAddress.Trim)
        ep = New IPEndPoint(remoteIPAddress, CType(PPort.Trim, Integer))

        ' Set the socket up (type etc)
        tnSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)

        Try
            ' Connect
            tnSocket.Connect(ep)
        Catch oEX As SocketException
            ' error
            ' Do error cleanup here e.g killing the socket
            ' and exiting the procedure.
            remoteIPAddress = Nothing
            ep = Nothing
            tnSocket = Nothing
            Exit Sub
        End Try
    End Sub

    Private Function sendCommand() As String
        wizScheduleCheckerMain.updateStatus("Sending command(s) to BeyonWiz box: ", "")
        ' NumBytes: Number of bytes return from telnet socket (count)
        Dim NumBytes As Integer = 0

        ' RecvString: data returned from the telnet socet
        Dim RecvString As String = String.Empty

        ' Create a byte array for recieving bytes from the telnet socket
        Dim RecvBytes(255) As [Byte]

        ' If we get to here then all seems good (we are connected)
        Try
            ' Wait a few seconds (3) (depending on connection) telnet can be slow.
            Dim cnt = 0
            Do
                System.Threading.Thread.Sleep(100)
                cnt = cnt + 1
            Loop Until tnSocket.Connected Or cnt > 100


            ' Double check we are connected
            If tnSocket.Connected Then

                wizScheduleCheckerMain.updateStatus("Connection Established", "")
                Dim count As Int16 = 0
                For Each cmd As String In commandList

                    ' Convert the ASCII command into bytes, adding a line termination on (vbCrLf)
                    Dim SendBytes As [Byte]() = st.Encoding.ASCII.GetBytes(cmd & vbCrLf)

                    count = count + 1
                    wizScheduleCheckerMain.updateStatus("Executing command ", count.ToString & " of " & commandList.Count)
                    ' Send the command
                    tnSocket.Send(SendBytes, SendBytes.Length, SocketFlags.None)
                    waitUntilReady(tnSocket)

                    ' loop getting 256 bytes of data from telnet socket at a time
                    Do
                        wizScheduleCheckerMain.updateStatus("Executing command " & count.ToString & " of " & commandList.Count, " - Getting response of length so far " & RecvString.Length)
                        ' RecvBytes with contain 256 bytes if data returned
                        ' numbytes with have the count of bytes returned
                        'System.Threading.Thread.Sleep(telnetDelay + 1000)
                        waitUntilReady(tnSocket)

                        NumBytes = tnSocket.Receive(RecvBytes, RecvBytes.Length, 0)
                        RecvString = RecvString + System.Text.Encoding.ASCII.GetString(RecvBytes, 0, NumBytes)

                    Loop While NumBytes = 256 ' if less than 256 we are at the end of the recv stream
                Next cmd
            End If
        Catch oEX As Exception
            ' Error cleanup etc needed

            endconnection()
        End Try

        Return RecvString
    End Function

    Private Function waitUntilReady(ByVal tnSocket As System.Net.Sockets.Socket) As Integer
        System.Threading.Thread.Sleep(100)
        Dim countr As Integer = 0
        While Not tnSocket.Poll(10, SelectMode.SelectRead)
            System.Threading.Thread.Sleep(50)
            countr = countr + 1
        End While
        Return countr
    End Function

    Private Sub endconnection()
        wizScheduleCheckerMain.updateStatus("Closing connection to BeyonWiz box: ", "")
        Try
            ' Disconnect
            tnSocket.Disconnect(False)

        Catch oEX As Exception
            ' Error cleanup etc needed
        End Try

        ' Cleanup
        remoteIPAddress = Nothing
        ep = Nothing
        tnSocket = Nothing

    End Sub

End Class
